﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;

namespace DiracTCC.Business
{
    public class YuvToBmpConverter
    {
        private string helperAppsPath;
        private VideoInfo video;

        Process pbmp;
        Process prgb;

        public event EventHandler NewFrameConvertedToRGB;
        public event EventHandler ConvertToRGBCompleted;
        public event EventHandler NewFrameConvertedToBMP;
        public event EventHandler ConvertToBMPCompleted;

        public YuvToBmpConverter(VideoInfo video, string helperAppsPath)
        {
            this.video = video;
            this.helperAppsPath = helperAppsPath;
        }

        public void ConvertToRGB(string originalPath)
        {
            prgb = new Process();
            switch (video.Chroma)
            {
                case Chroma.YUV444:
                    prgb.StartInfo.FileName = Path.Combine(helperAppsPath, "YUV444toRGB.exe");
                    break;
                case Chroma.YUV422:
                    prgb.StartInfo.FileName = Path.Combine(helperAppsPath, "YUV422toRGB.exe");
                    break;
                case Chroma.YUV420:
                    prgb.StartInfo.FileName = Path.Combine(helperAppsPath, "YUV420toRGB.exe");
                    break;
                default:
                    return;
                    break;
            }
            string newPath = Path.ChangeExtension(originalPath, ".rgb");
            prgb.StartInfo.CreateNoWindow = true;
            prgb.StartInfo.Arguments = string.Format("\"{0}\" \"{1}\" {2} {3} {4}", originalPath, newPath, video.VideoSize[0], video.VideoSize[1], video.NumberOfFrames);
            prgb.OutputDataReceived += new DataReceivedEventHandler(InformRGBAdvanceHandler);
            prgb.StartInfo.RedirectStandardOutput = true;
            prgb.StartInfo.UseShellExecute = false;
            prgb.Start();
            prgb.BeginOutputReadLine();
        }

        public void ConvertToBMP(string bmpPath, string videoPath)
        {
            string newPath = bmpPath.Substring(0, bmpPath.LastIndexOf('{'));
            string folderPath = newPath.Substring(0, newPath.LastIndexOf('\\'));

            if (!Directory.Exists(folderPath))
                Directory.CreateDirectory(folderPath);

            pbmp = new Process();
            pbmp.StartInfo.FileName = Path.Combine(helperAppsPath, "RGBtoBMP.exe");
            pbmp.StartInfo.Arguments = string.Format("\"{0}\" \"{1}\" \"{2}\" {3} {4} {5} {6} {7}", videoPath, newPath, ".bmp", "6", "1", video.NumberOfFrames + 1, video.VideoSize[0], video.VideoSize[1]);
            pbmp.OutputDataReceived += new DataReceivedEventHandler(InformBMPAdvanceHandler);
            pbmp.StartInfo.RedirectStandardOutput = true;
            pbmp.StartInfo.UseShellExecute = false;
            pbmp.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            pbmp.Start();
            pbmp.BeginOutputReadLine();
        }

        public static string GetBMPPath(string videoPath)
        {
            string bmpFolderPath = Path.Combine(
                    Path.GetDirectoryName(videoPath), "bmp_" + Path.GetFileNameWithoutExtension(videoPath));

            string bmpPath =
                Path.Combine(
                    bmpFolderPath,
                    Path.GetFileNameWithoutExtension(videoPath));

            return bmpPath + "{0:D6}.bmp";
        }

        void InformBMPAdvanceHandler(object sender, DataReceivedEventArgs e)
        {
            // if there is no data, it is finished
            if (e.Data == null)
            {
                if (ConvertToBMPCompleted != null)
                {
                    ConvertToBMPCompleted(this, new EventArgs());
                }

                pbmp.Dispose();
                return;
            }

            // inform event
            if (NewFrameConvertedToBMP != null)
            {
                NewFrameConvertedToBMP(this, new EventArgs());
            }
        }

        void InformRGBAdvanceHandler(object sender, DataReceivedEventArgs e)
        {
            // if there is no data, it is finished
            if (e.Data == null)
            {
                if (ConvertToRGBCompleted != null)
                {
                    ConvertToRGBCompleted(this, new EventArgs());
                }
                prgb.Dispose();
                return;
            }

            // inform event
            if (NewFrameConvertedToRGB != null)
            {
                NewFrameConvertedToRGB(this, new EventArgs());
            }
        }
    }
}
